Repository navigation
Adapter: find a project, launch a thread and read its status in-process - #36
Merged
Merged
Conversation
Ports softfac's find_project and status cases from src/t3.rs, adds launch and thread cases, and a contract test over the real orchestration layers with the Claude replay transcript. Red: paths.ts and sessions.ts do not exist yet, so none of the three files compile. Issue: #5
FactorySessions ports softfac's Sessions trait in-process: findProject over ProjectStoreV2, launch over ThreadLaunchService (new worktree from baseRef or the origin tip, full-access, default interaction, the caller's command id so a retry is the same launch), status and thread over ProjectionStoreV2 with softfac's run selection. FactoryPaths gives the base dir, the worktrees dir and <base>/factory from ServerConfig. The contract test waits for the run through EventSinkV2.stream with take(1): Stream.filterMap takes a Filter in Effect 4, not an Option, so the first draft never matched, and the test runs on the live clock because the orchestration runtime does not advance a TestClock. Issue: #5
From review cycle 1. Red: a blank commandId or threadId escapes as a schema defect instead of SessionsError / ThreadNotFoundError. The two-assistant-messages case is green already; it pins findLast against find, which every earlier test let through. Issue: #5
CommandId.make and ThreadId.make throw on a blank id. Decode the ids inside the Effect instead: a blank command, project or instance id is a launch SessionsError, and a blank thread id names no thread. Issue: #5
rawphp
marked this pull request as ready for review
October 15, 2026 11:16
Author
|
Factory gate: passed (attempt 1, run by the factory in a fresh checkout of the pull request's head
|
status is polled per session, so it now reads the runs and assistant messages through getThreadRecords instead of loading the whole thread projection. Adds tests for blank project and provider instance ids, thread read errors and project store failures failing as sessions errors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5
Contract
FactoryPathsgives baseDir, worktreesDir and<base>/factoryfromServerConfig.FactorySessionsports softfac'sSessionstrait in-process:findProjectoverProjectStoreV2(exact root, live projects only);launchoverThreadLaunchService(new worktree frombaseRef, or the origin tip whenstartFromOrigin,full-access, default interaction, the caller'scommandId, so the same id again returns the same thread and starts nothing);statusandthreadoverProjectionStoreV2with softfac's run selection (highest ordinal, skipping a cancelled run that never started unless every run is one; that run's own last assistant message; branch, worktreePath, archived).threadreads the thread row alone.events.ts,process.ts, wiring intoFactoryLayer, HTTP routes, ledger.vp test run apps/server/src/factory→ pass (42 tests);vp run --filter t3 typecheck→ passAcceptance criteria
sessions.tsprovidesFactorySessionswithfindProject,launch,status,thread, softfac's inputs and the ten run statuses —sessions.ts(RUN_STATUSES,LaunchRequest,FactorySessions);sessions.test.ts"maps every known run status".statusreports the latest run leaving out a cancelled run that never started, that run's last assistant message, and branch / worktreePath / archived —sessions.test.tsthreadStatusOfblock: 16 cases ported from softfacsrc/t3.rsplus "reports only the reported run's own last assistant message" and "reports the last of the run's assistant messages, not the first"; "reads a real recorded snapshot" against softfac'st3_thread_snapshot.json.threadreports the thread fields alone and works when the run cannot be read —sessions.test.ts"thread reads the thread's own fields and works when the runs cannot be read" (getThreadProjectionfails,getThreadanswers).launchstarts a thread in a new worktree frombaseRef/ origin tip,full-access, default interaction, given model, title, message, under the caller'scommandId; a repeatedcommandIdreturns the same thread and starts nothing —sessions.test.ts"starts a thread in a new worktree, full-access, default interaction, under the caller's command id" (asserts every field of theThreadLaunchInput, includingstartFromOrigin: true);sessions.contract.test.ts(second launch → same thread id,runOrdinalstays 1, run stayscompleted).paths.tsgives base dir, worktrees dir and<base>/factoryfromServerConfig—paths.test.ts.sessions.contract.test.tsruns the real orchestration layers with the provider-testing replay (Claudesimpletranscript throughProviderReplayHarness.layerWithRegistry, realThreadLaunchService, real git worktree throughGitVcsDriver): launches, waits forrun.updatedto reach a terminal status throughEventSinkV2.stream, reads "fixture simple ok", checks the worktree's.gitexists under the worktrees dir, thatgit branch --show-currentequalsstatus.branchandHEADequals the base ref, then repeats thecommandId. Runs in about 5 s.factory/t3/imports T3 internals —boundary.test.tsin the gate run;factory/scripts/check-seams.shexit 0 (no upstream file touched, no new seam).Gate
vp test run apps/server/src/factory→ exit 0 (6 files, 42 tests) —.factory/gate-1.logvp run --filter t3 typecheck→ exit 0 —.factory/gate-2.logModels
.dw/config.ymlhas nomodelsblock, so Tom's roster applied, and Make ran in-session after the Contract research rather than in a sonnet-5-5 worker)correctness,testing)Review
commandId/projectId/instanceId/threadIdthrew a schema defect fromCommandId.makeinstead of failing asSessionsError/ThreadNotFoundError(softfac returnsInvalidInput);findLastvsfindfor the last assistant message had no test with two assistant messages in one run.archivedwitharchivedAt === undefined(T3 types itNullOr, never undefined).Notes
origin/main(issue Factory skeleton: an empty FactoryLayer wired in through one seam #1 had landed); fast-forwardede4bcce9f6→f1dba9a17before provisioning. The firstvp ifailed on a transient.git/configlock in the primary checkout; the retry succeeded.factory:*labels already existed; none created.creationSourceis"server"(softfac sent"web"over the wire). The correctness reviewer checked: nothing in T3 branches on it forcreatedBy: "user", and in-process callers (serverRuntimeStartup,UsageLimitRecoveryWorker) already use"server".test:commits were red before their fix:f2e3f81f4(modules missing),55551d4a5(2 failures observed before24a0161ce). The two-assistant-messages case in55551d4a5was green already; it pinsfindLast.gh pr create(no-R) opened the PR on upstreampingdotgg/t3codeas Adapter: find a project, launch a thread and read its status in-process pingdotgg/t3code#19865, becauseghresolves a fork's parent as the default repository. Closed it at once with a comment; nothing else was written there. The real PR is this one, opened with-R original-solutions/t3code-factory.RunStatus::Unknownhas no counterpart: in-process the projection status is a closed literal union, so a new upstream status fails typecheck instead.Lessons
gh pr createneeds-R <owner/repo>. Symptom: the draft PR landed on the upstream repository the fork was cut from, with the fork issue'sCloses #npointing at a stranger's issue. Cause:ghpicks the parent repository as the default for a fork's remote. Default: always pass-R <factory repo>(and--head <branch>) togh pr create,gh pr editandgh pr list, and check the printed URL's owner before reporting it.Effect.timeoutOptionnever fired; console output was invisible once the test passed. Cause:it.effectruns under a TestClock the runtime never advances, and vitest hides stdout of passing tests. Default: useit.livefor runtime contract tests, and when a wait hangs, fork a stored-event logger that appends to a file under.factory/before the action under test, then compare where the pipeline stopped against where the wait subscribed.Stream.filterMapreturningOption.none()matched nothing in Effect 4 (it takes aFilter), so every variant of the wait returned empty. Default:grep "^export const <name>" node_modules/<lib>/src/<Module>.tsbefore the first use; preferStream.filter+Stream.take(1)+Stream.runCollectfor "first matching event".grep -nthe target lines and patch against what is there.Commits
f2e3f81f4test(factory): sessions and paths adapter cases— Make slice (red)53d91d5b8feat(factory): sessions adapter over T3's launch and projection services— Make slice55551d4a5test(factory): blank ids fail typed, last assistant message is the last— Check cycle 1 (red)24a0161cefix(factory): blank ids fail as the declared sessions errors— Check cycle 1Files
apps/server/src/factory/t3/sessions.ts— the adapter: types,threadStatusOf,FactorySessionsservice and layerapps/server/src/factory/t3/paths.ts—FactoryPathsfromServerConfigapps/server/src/factory/t3/sessions.test.ts— ported softfac status and find_project cases; launch, status, thread over mocks and a real in-memoryProjectStoreV2apps/server/src/factory/t3/sessions.contract.test.ts— real orchestration layers, Claude replay transcript, real git worktreeapps/server/src/factory/t3/paths.test.ts— paths from aServerConfigapps/server/src/factory/t3/fixtures/t3_thread_snapshot.json— softfac's recorded thread snapshot, copied fromtests/fixtures